<?php
/**
 * crcl/base
 *
 * Copyright 2013 CRCL - André Sabosch - info@crcl.de
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace crcl\base\exception;

interface IHandler
{
  /**
   * Sets exception handler, error handler, shutdown function
   *
   * @static
   */
  public static function setExceptionAndErrorHandler();

  /**
   * Handles Exception: collects data, executes internal printer, executes external logger service
   *
   * @param $e  Exception
   */
  public static function handleException($e);

  /**
   * Handles Error: collects data, executes internal printer, executes external logger service
   *
   * @param $iError
   * @param $sError
   * @param $sFile
   * @param $iLine
   * @param $aContext
   */
  public static function handleError($iError, $sError, $sFile, $iLine, $aContext);

  /**
   * Handles fatal error: collects data, executes internal printer, executes external logger service
   */
  public static function handleFatal();
}

class Handler implements IHandler
{
  public static function setExceptionAndErrorHandler()
  {
    \set_exception_handler(array('\crcl\base\exception\Handler', 'handleException'));
    \set_error_handler(array('\crcl\base\exception\Handler', 'handleError'));
    \register_shutdown_function(array('\crcl\base\exception\Handler', 'handleFatal'));
  }

  //not testable because of "die();"
  //@codeCoverageIgnoreStart
  public static function handleException($e)
  {
    $oData = Data::fromException($e);
    Printer::getInstance(\crcl\base\Tier::toString())->write($oData);
    die();
  }
  //@codeCoverageIgnoreEnd

  //not testable because of "die();"
  //@codeCoverageIgnoreStart
  public static function handleError($iError, $sError, $sFile, $iLine, $aContext)
  {
    if (\error_reporting() !== 0) //do not process error which are masked by @
    {
      $oData = Data::fromError($iError, $sError, $sFile, $iLine, $aContext);
      Printer::getInstance(\crcl\base\Tier::toString())->write($oData);
      die();
    }
  }
  //@codeCoverageIgnoreEnd

  //not testable because of "die();"
  //@codeCoverageIgnoreStart
  public static function handleFatal()
  {
    $aError = \error_get_last();

    if (isset($aError['type']))
    {
      if ($aError['type'] === \E_ERROR) //fatal error
      {
        $oData = Data::fromError(
          $aError['type'], $aError['message'], $aError['file'], $aError['line']);
        Printer::getInstance(\crcl\base\Tier::toString())->write($oData);
        die();
      }
    }
  }
  //@codeCoverageIgnoreEnd
}